#ifndef TIMED_MULTISET_H
#define TIMED_MULTISET_H

#include "colorset.h"
#include "multiset.h"
#include "wfnettypes.h"

#include <btime.h>
#include <coretypes.h>
#include <imultiset.h>
#include <type.h>

#include <QtCore/QHash>
#include <QtCore/QPair>

namespace wfnet
{

class TimedMultiset : public net::IMultiset, public core::Type
{
public:
    typedef QList<core::BasicTime> TimeStampList;
    typedef QPair<ColorSet, BasicTime> CombinedKey;
    typedef QSet<CombinedKey>::const_iterator ConstIterator;

private:
    typedef class QHash<CombinedKey, uint>::iterator PrivateIterator;
    typedef class QHash<CombinedKey, uint>::const_iterator ConstPrivateIterator;

    typedef class QHash<ColorSet, TimeStampList>::iterator TIterator;
    typedef class QHash<ColorSet, TimeStampList>::const_iterator TConstIterator;

public:
    TimedMultiset();
    TimedMultiset(const ColorSetName& colSetName);
    TimedMultiset(const ColorSetName& colSetName, const TypeValue& value);
    TimedMultiset(const TimedMultiset& other);
    TimedMultiset(const TimedMultiset& other, const TypeValue& value);
    ~TimedMultiset();

    // IMultiset
    bool isTimed() const;

    // Type
    QString name() const;
    bool matches(const TypeName& name) const;
    bool matches(const Type& type) const;
    bool canConvert(const TypeValue& value) const;
    ValueKeywordMask keywordMask() const;
    bool hasIdentity() const;
    void setIdentity(const Type& identity);

    Type* copy() const;

    TypeValue toValue() const;

    bool isEmpty() const;
    uint size() const;
    bool contains(const ColorSet& value,
        const core::BasicTime& time) const;
    uint coefficient(const ColorSet& value,
        const core::BasicTime& time) const;

    void insert(const ColorSet& value,
        const core::BasicTime& time);
    void remove(const ColorSet& value,
        const core::BasicTime& time);
    void clear();

    ColorSet at(uint index) const;
    TimedMultiset intersect(const TimedMultiset& other) const;

    TimedMultiset::TimeStampList getTimeStamps(
        const ColorSet& value) const;

    QList<QPair<ColorSet, BasicTime> > getSortedLowerValueList(
        core::BasicTime lowerThan) const;
    QList<QPair<ColorSet, BasicTime> > getSortedHigherValueList(
        core::BasicTime higherThan) const;

    bool getUpperBoundValue(ColorSet& bound, core::BasicTime& time,
        core::BasicTime of) const;

    TimedMultiset operator+(const TimedMultiset& other) const;
    TimedMultiset operator+(const BasicTime& time) const;
    TimedMultiset operator-(const TimedMultiset& other) const;
    TimedMultiset operator*(uint scalar) const;

    bool operator<=(const TimedMultiset& other) const;

    TypeName typeOf() const;

    Multiset toMultiset() const;

    ConstIterator constBegin() const;
    ConstIterator constEnd() const;

    static TypeName constructName(const ColorSetName& name);

private:
    void parseValue(const TypeValue& value);
    void fillOperations();
    uint coefficient(const ColorSet& value) const;

public:
    static const TypeName NAME;
    static const ValueKeywordMask KEYWORD_MASK;

private:
    TypeName m_colSetName;
    QHash<CombinedKey, uint> m_values;
    QHash<ColorSet, TimeStampList> m_timeStamps;
    TypeName m_name;
};

}  // namespace wfnet

#endif
